//
//  netSocket.cpp
//
//  Created by fox on 12-11-19.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#include "netsocket.h"
#include "netserver.h"
#include "logManager.h"

using namespace FOXSDK;

//mutex   netSocket::mMutex;

netSocket::netSocket( io_service& io_service ):tcp::socket ( io_service ) ,
    mHeadBuffer( buffer( mRecvBuffer , sizeof(netMsgHead) ) ),
    mBodyBuffer( buffer( mRecvBuffer + sizeof(netMsgHead) , MAX_SOCKET_BUFFER - sizeof(netMsgHead) ) ) ,
    mSendBuffer1( buffer( mSendBuffer , MAX_SOCKET_BUFFER ) ),
    mBodyLen( 0 ) , mRecvStage( FSRS_NULL ) ,
    mVaild( 0 ) ,
    mSend( 0 ) ,
    mClose( 0 ) ,
    mTimer( io_service )
{
    
    mServer = (netServer*)&io_service;
    
    mIBuffer.InitBuffer( MAX_IBUFFER_CACHE );
    mOBuffer.InitBuffer( MAX_OBUFFER_CACHE );
}

netSocket::~netSocket()
{
    
}


void    netSocket::close()
{
    tcp::socket::close();
}

fint32      netSocket::ReadMsg( netMsgHead** head )
{
    if ( !mVaild ) 
    {
        return 0;
    }
    
    int len = mIBuffer.GetLen();
    
    if ( len ) 
    {
        *head = (netMsgHead*)mIBuffer.GetBuffer();
        
        if ( (*head)->size > len )
        {
            return 3;
        }
        
        return 2;
    }
    
    return 1;
}

fvoid       netSocket::RemoveMsg( fint32 len )
{
    mIBuffer.RemoveBuffer( len );
}


fvoid       netSocket::RecvMsg( const boost::system::error_code& ec, size_t bytes_transferred )
{
    
    mTimer.cancel();
    
    if ( ec ) 
    {
        Clear();
        mServer->SetAccept( this );
        return;
    }
    else
    {
        if ( mClose )
        {
            Clear();
            mServer->SetAccept( this );
            return;
        }
        else
        {
            switch ( mRecvStage )
            {
                case (fint32)FSRS_HEAD:
                {
                    netMsgHead* head = (netMsgHead*)mRecvBuffer;
                    mBodyLen = head->size;
                    
                    //printf( "FSRS_HEAD %ld %d \n" , bytes_transferred , mBodyLen );
                    
                    if ( mBodyLen == 0 )
                    {
                        Clear();
                        mServer->SetAccept( this );
                        
                        return;
                    }
                    
                    if ( mBodyLen == sizeof( netMsgHead ) )
                    {
                        mIBuffer.Write( mRecvBuffer , sizeof( netMsgHead) );
                        ReadHead();
                        return;
                    }
                    else
                    {
                        mRecvStage = FSRS_BODY;
                        ReadBody();
                        return;
                    }
                }
                    break;
                case (fint32)FSRS_BODY:
                {
                    //printf( "FSRS_BODY %ld %d \n" , bytes_transferred , mBodyLen );
   
                    mIBuffer.Write( mRecvBuffer , mBodyLen );
                    mRecvStage = FSRS_HEAD;
                    ReadHead();
                    return;
                }
                    break;
                default:
                {
                    assert( 0 );
                }
                    break;
            }
        }
        
    }
}


fvoid       netSocket::Clear()
{
    if ( !mVaild )
    {
        return;
    }
    
    mVaild = 0;
    
    mRecvStage = FSRS_NULL;
    
    mBodyLen = 0;
    
    mIBuffer.ClearBuffer();
    mOBuffer.ClearBuffer();
    
    mSend = 0;
    
    //FLOG( LOGLEVEL0 , "OnNetMsgExit %s" , this->remote_endpoint().address().to_string().c_str() );
    
    mTimer.cancel();
    
    close();
}


fvoid       netSocket::ParkMsg( netMsgHead* head )
{
    mOBuffer.Write( (fbyte*)head , head->size );
}


fvoid       netSocket::SendMsg()
{
    if ( !mSend ) 
    {
        int len = mOBuffer.ReadRemove( &mSendBuffer );
        
        if ( len )
        {
            mSend = 1;
            
            async_write( *this , mSendBuffer1 , transfer_exactly( len ) , boost::bind( &netSocket::SendMsg , this , boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred )  ) ;
        }
    }
}


fvoid       netSocket::SendMsg( const boost::system::error_code& ec, size_t bytes_transferred )
{
    if ( ec )
    {
        Clear();
        mServer->SetAccept( this );
    }
    else
    {
        int len = mOBuffer.ReadRemove( &mSendBuffer );
        
        if ( len )
        {
            async_write( *this , mSendBuffer1 , transfer_exactly( len ) , boost::bind( &netSocket::SendMsg , this , boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred )  ) ;
        }
        else
        {
            mSend = 0;
        }
    }
    
}


void        netSocket::HandleWait( const boost::system::error_code& error )
{
    if ( error )
    {
        return;
    }
    
    this->Clear();
    mServer->SetAccept( this );
}

fvoid       netSocket::ReadHead()
{
    async_read( *this , mHeadBuffer ,
               transfer_at_least( sizeof(netMsgHead) ) ,
               boost::bind( &netSocket::RecvMsg , this , boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) ;
    
//    mTimer.expires_from_now( boost::posix_time::seconds( 120 ) );
//    mTimer.async_wait( boost::bind( &netSocket::HandleWait , this , boost::asio::placeholders::error ) );
}


fvoid       netSocket::ReadBody()
{
    async_read( *this , mBodyBuffer ,
               transfer_at_least( mBodyLen - sizeof(netMsgHead) ) ,
               boost::bind( &netSocket::RecvMsg , this , boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) ;
    
//    mTimer.expires_from_now( boost::posix_time::seconds( 120 ) );
//    mTimer.async_wait( boost::bind( &netSocket::HandleWait , this , boost::asio::placeholders::error) );
}


fvoid       netSocket::Run()
{
    mRecvStage = FSRS_HEAD;
    
    mVaild = 1;

    ReadHead();
}




